#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib2, urllib
import gobject, gtk, time, threading
from FileLock import FileLock
from Message import Message
import urlparse
import os, sys
class Dthread(threading.Thread):
    
    def __init__(self, url, path, model, iter):
        super(Dthread, self).__init__()
        self.opener = urllib2
        self.path = os.path.join(os.getcwd(), path)
        self.url = url
        self.chunckSize = 16384
        self.model = model
        self.iter = iter
        self.cancel = False
        self.getFilename()
    
    def setChunck(self, size):
        self.chunkSize = size
    
    def cancelDownload(self):
        self.cancel = True
    
    def __checkCancel(self):
        return self.cancel
    
    def start(self):
        super(Dthread, self).start()
        
    
    def parseFilename(self, meta):
        disposition = meta.getheaders('Content-Disposition')
        filetype = meta.getheaders('Content-type')
        subname = ""
        filename = ""
        if disposition:
            filename = urllib.unquote_plus(disposition[0].split('filename="')[1].split('"')[0])
            print filename
            if filename:
                self.path = os.path.join(self.path, filename)
            else:
                if filetype:
                    subname = filetype[0].split('/')[1].split(';')[0]
                else:
                    subname = "txt"
                self.path = os.path.join(self.path, 'unknown.'+subname)
        else:
            urlSplit = urlparse.urlsplit(self.url)
            print urlSplit
            filename = urllib.unquote_plus(urlSplit[2].split('/')[-1])
            if filename:
                self.path = os.path.join(self.path, filename)
            else:
                if filetype:
                    subname = filetype[0].split('/')[1].split(';')[0]
                else:
                    subname = 'txt'
                self.path = os.path.join(self.path, urlSplit[1]+'.'+subname)
                
    def getFilename(self):
        req = self.opener.Request(self.url)
        req.add_header('Content-type', '')
        try:
            resp = self.opener.urlopen(req)
            meta = resp.info()
            self.parseFilename(meta)
            return
        except ValueError:
            pass
        except urllib2.HTTPError as e:
            pass
        except urllib2.URLError:
            pass
        except:
            pass
        
                
    def getPath(self):
        return self.path
        
    def run(self):
        req = self.opener.Request(self.url)
        req.add_header('Content-type', '')
        try:
            resp = self.opener.urlopen(req)
            
            meta = resp.info()
            length = meta.getheaders("Content-Length")
            #self.parseFilename(meta)
            
            lockTime = -1
            if length:
                lockTime = int(float(length[0])/self.chunckSize)
                gobject.idle_add(self.model.set_value, self.iter, 2, length[0]+' bytes')
            self.lock = FileLock(self.path, lockTime, 0.5)
            self.lock.acquire(self.__checkCancel)
            f = open(self.path, 'wb')
            l = 0
            while not self.cancel:
                try:
                    data = resp.read(self.chunckSize)
                    if not data:
                        break
                    f.write(data)
                    l += len(data)
                    if length:
                        gobject.idle_add(self.model.set_value, self.iter, 5, str(int(l*100/float(length[0])))+'%')
                    gobject.idle_add(self.model.set_value, self.iter, 3, str(l)+' bytes')
                    time.sleep(0)
                except IOError:
                    gobject.idle_add(self.model.set_value, self.iter, 4, 'fail')
                    f.close()
                    self.lock.release()
                    resp.close()
                    return
            if not self.cancel:
                gobject.idle_add(self.model.set_value, self.iter, 4, 'done')
            f.close()
            self.lock.release()
            resp.close()
            print>>sys.stderr, "Download:run stopped"
            return
        except ValueError:
            gobject.idle_add(Message.urlValueError)
        except urllib2.HTTPError as e:
            gobject.idle_add(Message.urlAuthError, e.code)
        except urllib2.URLError:
            gobject.idle_add(Message.urlConnectionError)
        except:
            gobject.idle_add(Message.uncaughtError)
        gobject.idle_add(self.model.set_value, self.iter, 4, 'fail')

class Downloader(object):
    def __init__(self, url, path, model, iter):
        self.path = os.path.join(os.getcwd(), path)
        self.url = url
        self.model = model
        self.iter = iter
        self.thread = Dthread(self.url, self.path, self.model, self.iter)
        self.thread.daemon = True
        
    def setChunck(self, size):
        if self.thread:
            self.thread.setChunck(size)
    
    def cancel(self):
        self.model.set_value(self.iter, 4, 'cancel')
        self.thread.cancelDownload()
        if self.thread.isAlive():
            self.thread.join()
        #del self.thread
        self.thread = Dthread(self.url, self.path, self.model, self.iter)
        self.thread.daemon = True
        
    def delete(self):
        print>>sys.stderr, "Downloader:delete"
        self.thread.cancelDownload()
        if self.thread.isAlive():
            self.thread.join()
        print>>sys.stderr, "Downloader:deleted"
        #self.cancel()
        #del self.thread
    
    def start(self):
        if self.thread.isAlive():
            self.thread.cancelDownload()
            self.thread.join()
            #del self.thread
        self.thread = Dthread(self.url, self.path, self.model, self.iter)
        self.thread.daemon = True            
        self.thread.start()
        
    def getPath(self):
        return self.thread.getPath()

#if __name__ == '__main__':
#    Downloader("https://lh5.ggpht.com/_H2o_8CkoE3s/TA_nOt4vomI/AAAAAAAAAOU/lliTghwwljw/s1600-e365/test.jpg", "/tmp/newfile.jpg").start()
#    Downloader("https://lh5.ggpht.com/_H2o_8CkoE3s/TA_nOt4vomI/AAAAAAAAAOU/lliTghwwljw/s1600-e365/test.jpg", "/tmp/newfile.jpg").start()
